<template>
	<view class="container" id="my-drag-files">
		<el-container>
			<el-header class="head">
				<view class="head-left">
					<el-input placeholder="请输入键值" size="small" v-model="previewStr" clearable
						@input="handlerPreviewInput">
						<template slot="prepend">预览</template>
					</el-input>
					<el-button class="no-hover" size="small" plain icon="el-icon-info"
						@click="openDetails">信息</el-button>
					<el-button class="no-hover" size="small" plain icon="el-icon-upload2"
						@click="chooseImage">上传图片</el-button>
				</view>
				<view class="head-right">
					<view class="head-right-input">
						<el-tooltip class="item" effect="light" content="文件名不需要加后缀!" placement="bottom">
							<el-input placeholder="请输入文件名" size="small" v-model="fileName" clearable>
								<template slot="prepend">文件名</template>
							</el-input>
						</el-tooltip>
					</view>
					<view class="head-m-btn">
						<el-button class="no-hover" size="small" plain icon="el-icon-delete"
							@click="onDelAllItem">清空</el-button>
						<el-button class="no-hover" size="small" plain icon="el-icon-download"
							@click="onDownload">导出</el-button>
					</view>
				</view>

			</el-header>
			<el-main class="content">
				<view v-if="fileList.length == 0" class="content-container" @click="chooseImage">
					<i class="el-icon-upload icon"></i>
					<div class="el-upload__text">将图片拖到此处，或<em>点击选择图片</em></div>
				</view>
				<view class="content-table" v-if="fileList.length != 0">
					<el-table :data="fileList" :row-style="tableRowStyle" :header-cell-style="tableHeaderColor"
						size="mini" align="center" header-align="center" style="width: 100%">
						<el-table-column label="序号" width="50" align="center">
							<template slot-scope="scope">
								{{scope.$index+1}}
							</template>
						</el-table-column>
						<el-table-column label="尺寸" min-width="80" align="center">
							<template slot-scope="scope">
								<div class="content-table-template">{{scope.row.width}}*{{scope.row.height}}</div>
							</template>
						</el-table-column>
						<el-table-column label="大小" min-width="80" prop="size" align="center">
							<template slot-scope="scope">
								{{(scope.row.size/1024).toFixed(2)}}kb
							</template>
						</el-table-column>
						</el-table-column>

						<el-table-column label="图片" min-width="80" align="center" prop="url">
							<template slot-scope="scope">
								<el-image :src="scope.row.url" alt="" class="content-table-images" fit="contain"
									:preview-src-list="[scope.row.url]" />
							</template>
						</el-table-column>
						<el-table-column label="字符" align="center" min-width="80" prop="char">
							<template slot-scope="scope">
								<el-input placeholder="请输入字符" size="mini" v-model="scope.row.char"
									@input="handlerPreviewInput">
								</el-input>
							</template>
						</el-table-column>

						<el-table-column label="间距" align="center" min-width="80" prop="xadvance">
							<template slot-scope="scope">
								<el-input type="number" placeholder="请输入间距" size="mini" v-model="scope.row.xadvance"
									@input="handlerXadvanceInput(scope.$index)">
								</el-input>
							</template>
						</el-table-column>

						<el-table-column label="X偏移" align="center" min-width="80" prop="xoffset">
							<template slot-scope="scope">
								<el-input type="number" placeholder="请输入X偏移" size="mini" v-model="scope.row.xoffset"
									@input="handlerPreviewInput">
								</el-input>
							</template>
						</el-table-column>
						<el-table-column label="Y偏移" align="center" min-width="80" prop="yoffset">
							<template slot-scope="scope">
								<el-input type="number" placeholder="请输入X偏移" size="mini" v-model="scope.row.yoffset"
									@input="handlerPreviewInput">
								</el-input>
							</template>
						</el-table-column>
						<el-table-column label="缩放" align="center" prop="scale" min-width="60">
							<template slot-scope="scope">
								<el-input disabled placeholder="请输入缩放" size="mini" v-model="scope.row.scale"
									@input="handlerScaleInput(scope.$index)">
								</el-input>
							</template>
						</el-table-column>


						</el-table-column>
						<el-table-column label="操作" align="center">
							<template slot-scope="scope">
								<el-button size="mini" plain icon="el-icon-delete"
									@click.stop="onDelItem(scope.$index)"></el-button>
							</template>
						</el-table-column>
					</el-table>
				</view>

				<view class="canvas-container" v-if="fileList.length > 0 && previewStr.length > 0">
					<canvas class="previewCanvas"
						:style="{height:`${previewCanvasHeight}px`,width:`${previewCanvasWidth}px`}"
						canvas-id="previewCanvas"></canvas>
				</view>

				<view class="canvas-container" v-if="fileList.length > 0">
					<canvas class="canvas_font" :style="{height:`${fontCanvasHeight}px`,width:`${fontCanvasWidth}px`}"
						canvas-id="canvas_font"></canvas>
				</view>
			</el-main>
		</el-container>



		<el-dialog
		  :visible.sync="dialogVisible"
		  width="30%">
		  <el-descriptions class="margin-top" title="生成图片信息" :column="1" border>
		      <el-descriptions-item>
		        <template slot="label">文件名</template>
		        {{fileName.length>0?(fileName + '.png'):'-'}}
		      </el-descriptions-item>
		      <el-descriptions-item>
		        <template slot="label">尺寸</template>
		        {{fontCanvasWidth}}*{{fontCanvasHeight}}
		      </el-descriptions-item>
			  
		      <el-descriptions-item>
		        <template slot="label">散图</template>
		        {{fileList.length}}张
		      </el-descriptions-item>
		      <el-descriptions-item>
		        <template slot="label">Max FontSize</template>
		        {{fontSize}}px
		      </el-descriptions-item>
		    </el-descriptions>
		</el-dialog>
	</view>
</template>

<script>
	import {
		saveAs
	} from 'file-saver';
	const crypto = require('crypto');
	export default {
		data() {
			return {
				dialogVisible: false,
				previewStr: '',
				fileName: '',
				fileList: [],
				fontSize: 0,
				fontCanvasHeight: 0,
				fontCanvasWidth: 0,
				previewCanvasHeight: 170,
				previewCanvasWidth: 170,
				tableHeaderColor: {
					background: '#383b43 !important',
					color: '#d5d5d5',
					fontSize: '15px',
				}
			}
		},
		mounted() {
			//添加监听
			let elem = document.getElementById('my-drag-files');
			elem.addEventListener('drop', this.ondrop, false);
			elem.addEventListener('dragleave', this.ondropprevent);
			elem.addEventListener('dragenter', this.ondropprevent);
			elem.addEventListener('dragover', this.ondropprevent);
			this.elem = elem;
		},
		beforeDestroy() {
			const {
				elem
			} = this;
			//移除监听
			elem.removeEventListener('drop', this.ondrop);
			elem.removeEventListener('dragleave', this.ondropprevent);
			elem.removeEventListener('dragenter', this.ondropprevent);
			elem.removeEventListener('dragover', this.ondropprevent);
		},
		methods: {
			onOpenGitee(){
				window.open('https://gitee.com/coyeking/tool-library');
			},
			handlerXadvanceInput(index) {
				// this.fileList[index].scale = Number(this.fileList[index].xadvance) / this.fileList[index].width;
				this.updataPreviewCanvas();
			},
			handlerScaleInput(index) {
				// this.fileList[index].xadvance = Number(this.fileList[index].scale) * this.fileList[index].width;
				// this.updataPreviewCanvas();
			},
			handlerPreviewInput() {
				this.updataPreviewCanvas();
				setTimeout(()=>{
					this.updataPreviewCanvas();
				},10)
			},
			async getChooseImages() {
				return new Promise((resolve, reject) => {
					uni.chooseImage({
						count: 50,
						success: function(res) {
							resolve(res);
						}
					})
				});

			},
			async chooseImage() {
				let res = await this.getChooseImages();
				let files = res.tempFiles;
				this.setSeleData(files);
			},
			async setSeleData(files) {
				var _this = this;
				let _index = 0;
				let _index2 = 0;
				for (let i = 0; i < files.length; i++) {
					let file = files[i];
					let imageType = /^image\//;

					if (!imageType.test(file.type)) {
						_index++;
						continue;
					}
					let base64 = await this.getFileToBase64(file);
					let url = URL.createObjectURL(file);
					let md5 = _this.getBase64MD5(base64);
					let info = _this.validate(md5);
					if (info) {
						_index++;
						continue;
					}
					_index2++;
					let imageInfo = await this.getImageInfo(url);
					let fileName = file.name.split('.')[0];
					let data = {
						name: file.name,
						char: fileName.substr(fileName.length - 1, 1),
						size: file.size,
						url: url,
						width: imageInfo.width,
						height: imageInfo.height,
						md5: md5,
						xoffset: 0,
						yoffset: 0,
						scale: 1,
						xadvance: imageInfo.width,
					}
					_this.fileList.push(data);
					if ((_index + _index2) == files.length) {
						// console.log('fileList=>', _this.fileList);
						_this.updataPreviewCanvas();
						_this.updataCanvas();
						setTimeout(()=>{
							_this.updataPreviewCanvas();
							_this.updataCanvas();
						},10)
					}
				}

			},
			async ondrop(e) {
				this.ondropprevent(event);
				let files = event.dataTransfer.files;
				this.setSeleData(files);

			},
			ondropprevent(event) {
				event.stopPropagation();
				event.preventDefault();
			},
			tableRowStyle(row) {
				return row.rowIndex % 2 === 0 ? {
					'background': '#313339'
				} : {
					'background': '#383b43'
				};
			},
			async getImageInfo(url) {
				return new Promise((resolve, reject) => {
					uni.getImageInfo({
						src: url,
						success: function(imageInfo) {
							resolve(imageInfo)
						},
						fail: function(error) {
							console.error('获取图片信息失败：', error);
						}
					});
				});
			},
			async getFileToBase64(file) {
				return new Promise((resolve, reject) => {
					const reader = new FileReader();
					reader.readAsDataURL(file);
					reader.onload = (aImg) => {
						resolve(reader.result);
					}
					reader.onerror = (error) => reject(error);
				});
			},
			validate(md5) {
				let list = this.fileList;
				for (let j = 0; j < list.length; j++) {
					if (list[j].md5 == md5) return true;
				}
				return false;
			},
			getBase64MD5(base64Str) {
				// 将base64字符串解码为二进制数据
				const buffer = Buffer.from(base64Str, 'base64');
				// 使用MD5算法计算二进制数据的哈希值
				const md5Hash = crypto.createHash('md5');
				md5Hash.update(buffer);
				// 将哈希值转换为十六进制字符串
				return md5Hash.digest('hex');
			},
			/**  获取资源组最大高度*/
			getImgsMaxHeight() {
				let height = 0;
				imageList.forEach(img => {
					if (img.height > height) height = img.height;
				});
				return height;
			},
			updataCanvas() {
				let imageList = this.fileList;
				let len = imageList.length;
				const ctx = uni.createCanvasContext('canvas_font', this);
				let canvasWidth = 1024
				let canvasHeight = 1024
				this.fontCanvasHeight = canvasHeight;
				this.fontCanvasWidth = canvasWidth;
				ctx.clearRect(0, 0, canvasWidth, canvasHeight)
				let height = 0;
				let space = 2;
				let x = space;
				let y = space;
				let maxX = x;
				let maxY = y;
				imageList.forEach(img => {
					if (img.height > height) height = img.height;
				});
				height = Math.ceil(height);
				this.fontSize = height;
				imageList.forEach(img2 => {
					if (x + img2.width + space > canvasWidth) {
						x = space;
						y += height + space;
						if (y + height + space > this.fontCanvasHeight) {
							this.fontCanvasWidth += (x + img2.width + space);
							this.fontCanvasHeight += y;
						}
					}
					ctx.drawImage(img2.url, x, y);
					img2.x = x;
					img2.y = y;
					x += img2.width + space;
					if (maxX < x) {
						maxX = x;
					}
					if (maxY < y + height + space) {
						maxY = y + height + space;
					}
				});

				this.fontCanvasWidth = maxX + 2;
				this.fontCanvasHeight = maxY;
				ctx.draw();

			},
			updataPreviewCanvas() {
				let _string = this.previewStr;
				let textLen = _string.length;
				let imageList = this.fileList;
				if (imageList.length == 0 && textLen.length == 0) return;

				const ctx = uni.createCanvasContext('previewCanvas', this);
				let map = {}
				let height = 0;
				let width = 0;
				imageList.forEach(img => {
					map[img.char.charCodeAt(0)] = img;
				});

				for (let j = 0; j < textLen; j++) {
					let character = _string.charCodeAt(j);
					let img = map[character]
					if (img) {
						width += Number(img.xadvance);
						if (img.height > height) height = img.height;
					}
				}
				this.previewCanvasHeight = height;
				this.previewCanvasWidth = width;
				ctx.clearRect(0, 0, width, height);

				let startX = 0
				let y = 0
				for (let index = 0; index < textLen; index++) {
					let character = _string.charCodeAt(index);
					let img = map[character]
					if (img) {
						ctx.drawImage(img.url, startX + Number(img.xoffset), y + Number(img.yoffset));
						startX += Number(img.xadvance);
					}
				}
				ctx.draw();
			},
			onclick() {
				this.updataPreviewCanvas();
				this.updataCanvas();
				uni.chooseImage({
					success: function(res) {
						console.log(res);
					}
				})
				return;
			},
			onDelItem(index) {
				this.fileList.splice(index, 1)
				this.updataPreviewCanvas();
				this.updataCanvas();
			},
			onDelAllItem() {
				if (this.fileList.length == 0) return;
				this.$confirm('数据将清空, 是否继续?', '温馨提示', {
					confirmButtonText: '确定',
					cancelButtonText: '取消',
					type: 'warning'
				}).then(() => {
					this.fileList = [];
					const ctx = uni.createCanvasContext('previewCanvas', this);
					ctx.clearRect(0, 0, 20, 20);
					ctx.draw();
					this.previewCanvasHeight = 0;
					this.previewCanvasWidth = 0;
				}).catch(() => {});

			},
			openDetails(){
				this.dialogVisible = true;
			},
			onDownload() {
				var _this = this;
				if (this.fileList.length == 0) return;
				if (this.fileName.length == 0){
					this.$message({
					          message: '请输入保存的文件名！',
					          type: 'warning'
					        });
							return;
				} 

				let imageList = this.fileList;
				uni.canvasToTempFilePath({
					canvasId: 'canvas_font',
					success: function(res) {
						// 在H5平台下，tempFilePath 为 base64
						var arr = res.tempFilePath.split(',');
						var bytes = atob(arr[1]);
						let ab = new ArrayBuffer(bytes.length);
						let ia = new Uint8Array(ab);
						for (let i = 0; i < bytes.length; i++) {
							ia[i] = bytes.charCodeAt(i);
						}

						var blob = new Blob([ab], {
							type: 'application/octet-stream'
						});
						saveAs(blob, _this.fileName + ".png");

						let str =
							`info size=${_this.fontSize} unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0 common lineHeight=${_this.fontSize} base=23 scaleW=${_this.fontCanvasWidth} scaleH=${_this.fontCanvasHeight} pages=1 packed=0 page id=0 file="${_this.fileName}.png" chars count=${imageList.length}\n`;
						imageList.forEach(img => {
							str +=
								`char id=${img.char.charCodeAt(0)} x=${img.x} y=${img.y} width=${img.width} height=${img.height} xoffset=${img.xoffset} yoffset=${img.yoffset} xadvance=${img.xadvance} \n`;
						});
						let blob_font = new Blob([str], {
							type: "text/plain;charset=utf-8"
						});
						saveAs(blob_font, _this.fileName + ".fnt");
					}
				})
			}
		}
	}
</script>

<style lang="less" scoped>
	page {
		width: 100%;
		height: 100%;
		background: #383b43;
		width: 100%;
	}

	.container {
		width: 100%;
		height: 100%;
	}

	.head {
		background: #383b43;
		display: flex;
		flex-direction: row;
		flex-wrap: nowrap;
		align-items: center;
		justify-content: space-between;
		border-bottom: 1px solid #d9d9d9;
		color: #d9d9d9;
		position: fixed;
		z-index: 99;
		box-sizing: border-box;
		width: 100%;
			


		.head-left {
			.el-input {
				width: 170px;

				/deep/ .el-input-group__prepend {
					background-color: #313339;
					padding: 0 10px;
				}
			}

			.el-button {
				margin-left: 10px;
			}
		}

		.head-right {
			display: flex;

			.head-right-input {
				display: flex;
				flex-wrap: nowrap;
				user-select: text;
				margin-right: 10px;

				.el-input {
					width: 190px;

					/deep/ .el-input-group__prepend {
						background-color: #313339;
						padding: 0 10px;
					}
				}
			}
			.head-m-btn{
				display: flex;
				flex-direction: row;
				flex-wrap: nowrap;
				align-items: center;
			
				.head-m-image{
					margin-left: 10px;
					width: 30px;
					height: 30px;
					border-radius: 20px;
				}
			}
		}
	}



	.el-input /deep/ .el-input__inner {
		background-color: #000000;
		color: #fff;
		padding: 0 10px;
	}


	.content {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		margin-top: 60px;

		.content-container {
			width: 360px;
			height: 180px;
			margin-top: 150px;
			display: flex;
			flex-direction: column;
			align-items: center;
			justify-content: center;
			background-color: #313339;
			border: 1px dashed #d9d9d9;
			border-radius: 6px;

			.icon {
				font-size: 67px;
				color: #c0c4cc;
				margin: 40px 0 16px;
				line-height: 50px;
			}

			.el-upload__text {
				color: #606266;
				font-size: 14px;
				text-align: center;

				em {
					color: #409eff;
					font-style: normal;
				}
			}
		}

	}

	.content-table {
		width: 100%;
		border: 1px dashed #d9d9d9;

		.el-table /deep/ tbody tr:hover>td {
			background-color: #50535d !important;
		}

		.el-table /deep/ tbody tr {
			color: #fff;
		}

		.el-table::before {
			height: 0px;
		}
	}

	//去掉每行的下边框
	/deep/ .el-table td.el-table__cell,
	/deep/ .el-table th.el-table__cell.is-leaf {
		border-bottom: none;
		padding: 3px 0;
	}

	// 表格最外层边框-底部边框
	.el-table--border::after,
	.el-table--group::after {
		width: 0;
	}


	.content-table-template {
		white-space: nowrap;
		overflow: hidden;
		text-overflow: ellipsis;
	}

	.content-table-images {
		height: 38px;
		display: block;
		margin-left: auto;
		margin-right: auto;
		max-width: 100%;
	}

	/* 添加自定义类来覆盖悬停样式 */
	.el-button {
		background: #313339;
		color: #DCDFE6;

		&:hover {
			background-color: inherit;
			color: inherit;
			border-color: inherit;
			box-shadow: none;
		}

		&:focus {
			background-color: inherit;
			color: inherit;
			border-color: inherit;
			box-shadow: none;
		}
	}

	.canvas-container {
		margin-top: 20px;
		width: 100%;

		.previewCanvas {
			border: 1px solid #d9d9d9;
			background-color: #313339;
		}

		.canvas_font {
			border: 1px solid #d9d9d9;
			background-color: #636773;
		}
	}
	
	// 模态框居中
	::v-deep .el-dialog{
		   display: flex;
		   flex-direction: column;
		   margin:0 !important;
		   position:absolute;
		   top:50%;
		   left:50%;
		   transform:translate(-50%,-50%);
		   max-height:calc(100% - 30px);
		   max-width:calc(100% - 30px);
	   }
	  ::v-deep  .el-dialog .el-dialog__body{
		   flex:1;
		   overflow: auto;
	   }
</style>